﻿/*
 * Created by SharpDevelop.
 * User: Masy Freddy
 * Date: 15/09/2011
 * Time: 17:46
 */

namespace ProviderTheMovieDB
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Security.Cryptography;
	using System.Xml.Linq;
	using System.Xml.Serialization;
	using MetaVideoEditorEvolved.AddIn.AddInViews;
	using MetaVideoEditorEvolved.AddIn.Entity;
	using MetaVideoEditorEvolved.Helper;
	using System.Globalization;

	[System.AddIn.AddIn("TheMovieDb",
	                    Version = "1.0.0.0",
	                    Description = "Fournisseur d'accès de TheMovieDb",
	                    Publisher = "Masy Freddy")]
	public class TheMovieDBManager : ProviderView
	{
		private string apiKey = "ebb392e0588bc0b5ab9d9a6100711a8c",
		search = @"http://api.themoviedb.org/2.1/Movie.search/{0}/xml/{1}/{2}",
		getInfo = @"http://api.themoviedb.org/2.1/Movie.getInfo/{0}/xml/{1}/{2}";
		private ConfigurationAddIn configurationAddIn;
		
		public TheMovieDBManager()
		{
			configurationAddIn = ConfigurationManager.Deserialize();
			
			if(configurationAddIn == null)
			{
				configurationAddIn = new ConfigurationAddIn()
				{
					Language = "fr",
					TraceLevel = "Error"
				};
				ConfigurationManager.Serialize(configurationAddIn);
			}
			
			Tracer.TracerInstance.Level= string.IsNullOrEmpty(configurationAddIn.TraceLevel) ? TracerLevel.Error : (TracerLevel)Enum.Parse(typeof(TracerLevel), configurationAddIn.TraceLevel);
			Tracer.TracerInstance.FileName = "TheMovieDB";
		}
		
		public override List<MetaVideoEditorEvolved.AddIn.Entity.ProviderSearchResult> FindPossible(MetaVideoEditorEvolved.AddIn.Entity.ProviderSearchRequest request)
		{
			try
			{
				Tracer.TracerInstance.TraceInformation(string.Format("Start TheMovieDb FindPossible (SearchName:{0}-Type{1})", request.Name, request.Type.ToString()));
				
				List<ProviderSearchResult> results = new List<ProviderSearchResult>();
				
				if(request.Type == MediaType.Movie)
				{
					var resultWebRequest = DownloadManager.RetrieveXmlWebRequest(string.Format(search, configurationAddIn.Language, apiKey, MetaVideoEditorEvolved.Helper.DownloadManager.UrlEncode(request.Name)));
					
					if(resultWebRequest != null)
					{
						Tracer.TracerInstance.TraceInformation("Start to Deserialize");
						OpenSearchDescription searchMovie = new XmlSerializer(typeof(OpenSearchDescription)).Deserialize(resultWebRequest.Root.CreateReader()) as OpenSearchDescription;
						Tracer.TracerInstance.TraceInformation("End Deserialize");
						
						if(searchMovie != null)
						{
							foreach (var movie in searchMovie.movies) {
								ProviderSearchResult result = new ProviderSearchResult()
								{
									Id = string.IsNullOrEmpty(movie.id) ? 0 : int.Parse(movie.id),
									OriginalName = movie.original_name,
									Name = string.IsNullOrEmpty(movie.name) ? movie.original_name : movie.name,
									Overview = movie.overview,
									MediaUrl = string.IsNullOrEmpty(movie.url) ? null : new Uri(movie.url),
									Year = string.IsNullOrEmpty(movie.released) ? 0 : int.Parse(movie.released.Substring(0,4))
								};
								
								if(movie.images != null)
								{
									foreach (var image in movie.images) {
										if(image.type == "poster" &&
										   image.size == "thumb")
										{
											result.Picture = string.IsNullOrEmpty(image.url) ? null : new Uri(image.url);
											break;
										}
									}
								}
								
								results.Add(result);
							}
						}
					}
				}
				
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End TheMovieDb FindPossible (SearchName:{0}-Type{1}) with {2} items", request.Name, request.Type.ToString(), results.Count));
				
				return results;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError("Exception in TheMovieDB provider FindPossible (SearchName:{0}-Type{1})", ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		public override Movie FetchMovie(int movieId)
		{
			try
			{
				Tracer.TracerInstance.TraceInformation(string.Format("Start the TheMovieDbManager FetchMovie (MovieId:{0})", movieId));
				var resultWebRequest = DownloadManager.RetrieveXmlWebRequest(string.Format(getInfo, configurationAddIn.Language, apiKey, movieId));
				
				if(resultWebRequest != null)
				{
					Tracer.TracerInstance.TraceInformation("Start to Deserialize");
					OpenSearchDescription searchMovies = new XmlSerializer(typeof(OpenSearchDescription)).Deserialize(resultWebRequest.Root.CreateReader()) as OpenSearchDescription;
					Tracer.TracerInstance.TraceInformation("End Deserialize");
					
					if(searchMovies != null &&
					   searchMovies.movies != null &&
					   searchMovies.movies.Any())
					{
						var searchMovie = searchMovies.movies.First();
						
						Movie movie = new Movie()
						{
							Countries = new List<string>(),
							Genres = new List<string>(),
							CastMembers = new List<CastMember>(),
							Backdrops = new List<Uri>(),
							Posters = new List<Uri>(),
							Trailers = new List<Trailer>(),
							Studios = new List<string>()
						};
						
						movie.Id = string.IsNullOrEmpty(searchMovie.id) ? 0 : int.Parse(searchMovie.id);
						movie.OriginalTitle = searchMovie.original_name;
						movie.Title = string.IsNullOrEmpty(searchMovie.name) ? movie.OriginalTitle : searchMovie.name;
						movie.Overview = searchMovie.overview;
						movie.Year = string.IsNullOrEmpty(searchMovie.released) ? 0 : int.Parse(searchMovie.released.Substring(0,4));
						movie.Rating = string.IsNullOrEmpty(searchMovie.rating) ? 0.0F : float.Parse(searchMovie.rating, CultureInfo.InvariantCulture);
						movie.Duration = string.IsNullOrEmpty(searchMovie.runtime) ? 0 : int.Parse(searchMovie.runtime);
						movie.MPAARating = searchMovie.certification;
						
						if(searchMovie.categories != null)
						{
							foreach (var genre in searchMovie.categories) {
								movie.Genres.Add(genre.name);
							}
						}
						
						if(searchMovie.studios != null)
						{
							foreach (var studio in searchMovie.studios) {
								movie.Studios.Add(studio.name);
							}
						}
						
						if(searchMovie.countries != null)
						{
							foreach (var nationality in searchMovie.countries) {
								movie.Countries.Add(nationality.name);
							}
						}
						
						if(searchMovie.cast != null)
						{
							foreach (var casting in searchMovie.cast) {
								movie.CastMembers.Add(new CastMember()
								                      {
								                      	FullName = casting.name,
								                      	Role = casting.character,
								                      	Activity = casting.job,
								                      	Picture =  string.IsNullOrEmpty(casting.thumb) ? null : new Uri(casting.thumb)
								                      });
							}
						}
						
						if(searchMovie.images != null)
						{
							foreach (var image in searchMovie.images) {
								if(image.size == "original")
								{
									if(image.type == "poster")
									{
										movie.Posters.Add(new Uri(image.url));
									}
									
									if(image.type == "backdrop")
									{
										movie.Backdrops.Add(new Uri(image.url));
									}
								}
							}
						}
						Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the TheMovieDb FechMovie (Id:{0})", movieId));
						
						return movie;
					}
				}
				
				return null;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError("Exception in TheMovieDB provider FindPossible (SearchName:{0}-Type{1})", ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		public override Episode FetchEpisode(string serieId, int seasonNumber, int episodeNumber)
		{
			return null;
		}
		
		public override Season FetchSeason(string serieId, int seasonNumber)
		{
			return null;
		}
		
		public override Serie FetchSerie(string serieId)
		{
			return null;
		}
		
		public override void ShowOption()
		{
			new Option(configurationAddIn).ShowDialog();
		}
		
		public override bool HasOption()
		{
			return true;
		}
	}
}